package com.study.springmvc.servlet;

import com.study.springmvc.anno.Controller;
import com.study.springmvc.anno.RequestMapping;
import com.study.springmvc.context.BeanFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.reflections.Reflections;

/**
 * @author lupengwei 2021/5/17 10:25
 */
public class HandlerMappingResolver {
    
    
    private Map<String, Handler> handlerMapping;

    
    public HandlerMappingResolver(BeanFactory beanFactory, Properties properties) {
        getHandlerMapping(beanFactory, properties);
    }
    
    
    private void getHandlerMapping(BeanFactory beanFactory, Properties properties) {
        String scanPackage = properties.getProperty("spring.scan.package");
        Reflections reflections = new Reflections(scanPackage);
    
        handlerMapping = new HashMap<>(16);
        Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Controller.class);
        for (Class<?> aClass : classSet) {
            Controller classAnnotation = aClass.getAnnotation(Controller.class);
            String beanName = classAnnotation.value();
            beanName = "".equals(beanName) ? getSimpleName(aClass) : beanName;
            
            // 获取添加了 Controller 注解类的实例
            Object bean = beanFactory.getBean(beanName);
    
            // 处理添加了 RequestMapping 的注解
            Method[] methods = aClass.getMethods();
            for (Method method : methods) {
                RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                if (annotation == null) {
                    continue;
                }
                
                // URL
                String url = annotation.value();
                
                // 方法参数名称列表
                List<String> paramNameList = new ArrayList<>();
                Parameter[] parameters = method.getParameters();
                for (Parameter parameter : parameters) {
                    paramNameList.add(parameter.getName());
                }
                
                // 建立 URL 和 Handler 的映射关系
                Handler handler = new Handler();
                handler.setMethod(method);
                handler.setControllerObject(bean);
                handler.setParamNameList(paramNameList);
                handlerMapping.put(url, handler);
            }
        }
    }
    
    
    public Handler getHandler(HttpServletRequest req) {
        return handlerMapping.get(req.getRequestURI());
    }
    
    
    private static String getSimpleName(Class<?> aClass) {
        return toLowerCaseFirstChar(aClass.getSimpleName());
    }
    
    
    private static String toLowerCaseFirstChar(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        }
    }
}
